<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
<meta name="viewport" content="width=device-width">
<meta name="theme-color" content="#222"><meta name="generator" content="Hexo 7.3.0">

  <link rel="apple-touch-icon" sizes="180x180" href="/images/apple-touch-icon-next.png">
  <link rel="icon" type="image/png" sizes="32x32" href="/images/favicon-32x32.ico">
  <link rel="icon" type="image/png" sizes="16x16" href="/images/favicon-16x16.ico">
  <link rel="mask-icon" href="/images/logo.svg" color="#222">

<link rel="stylesheet" href="/css/main.css">



<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css" integrity="sha256-wiz7ZSCn/btzhjKDQBms9Hx4sSeUYsDrTLg7roPstac=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/3.1.1/animate.min.css" integrity="sha256-PR7ttpcvz8qrF57fur/yAx1qXMFJeJFiA6pSzWi0OIE=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.css" integrity="sha256-6cQIC71/iBIYXFK+0RHAvwmjwWzkWd+r7v/BX3/vZDc=" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/themes/green/pace-theme-minimal.css">
  <script src="https://cdnjs.cloudflare.com/ajax/libs/pace/1.2.4/pace.min.js" integrity="sha256-gqd7YTjg/BtfqWSwsJOvndl0Bxc8gFImLEkXQT8+qj0=" crossorigin="anonymous"></script>

<script class="next-config" data-name="main" type="application/json">{"hostname":"sumumm.github.io","root":"/","images":"/images","scheme":"Gemini","darkmode":false,"version":"8.19.2","exturl":false,"sidebar":{"position":"left","display":"post","padding":18,"offset":12},"copycode":{"enable":true,"style":"mac"},"fold":{"enable":true,"height":300},"bookmark":{"enable":false,"color":"#222","save":"auto"},"mediumzoom":false,"lazyload":true,"pangu":false,"comments":{"style":"tabs","active":null,"storage":true,"lazyload":false,"nav":null},"stickytabs":false,"motion":{"enable":true,"async":true,"transition":{"menu_item":"fadeInDown","post_block":"fadeIn","post_header":"fadeInDown","post_body":"fadeInDown","coll_header":"fadeInLeft","sidebar":"fadeInUp"}},"i18n":{"placeholder":"搜索...","empty":"没有找到任何搜索结果：${query}","hits_time":"找到 ${hits} 个搜索结果（用时 ${time} 毫秒）","hits":"找到 ${hits} 个搜索结果"},"path":"/search.xml","localsearch":{"enable":true,"trigger":"auto","top_n_per_article":1,"unescape":false,"preload":false}}</script><script src="/js/config.js"></script>

    <meta name="description" content="本文主要是STM32开发——内部FLASH基础知识的一些相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:type" content="article">
<meta property="og:title" content="LV16-27-内部Flash-01-基础知识">
<meta property="og:url" content="https://sumumm.github.io/post/37b707ef.html">
<meta property="og:site_name" content="苏木">
<meta property="og:description" content="本文主要是STM32开发——内部FLASH基础知识的一些相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530174140633.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530135945546.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530140426886.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530174859848.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175141413.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175015147.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175249232.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175343778.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531095555140.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531100044334.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531100517228.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531075735423.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531080159961.png">
<meta property="og:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20220924210401860.png">
<meta property="article:published_time" content="2023-06-04T14:07:46.000Z">
<meta property="article:modified_time" content="2025-06-13T16:25:57.015Z">
<meta property="article:author" content="苏木">
<meta property="article:tag" content="LV16-STM32开发">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530174140633.png">


<link rel="canonical" href="https://sumumm.github.io/post/37b707ef.html">



<script class="next-config" data-name="page" type="application/json">{"sidebar":"","isHome":false,"isPost":true,"lang":"zh-CN","comments":true,"permalink":"https://sumumm.github.io/post/37b707ef.html","path":"post/37b707ef.html","title":"LV16-27-内部Flash-01-基础知识"}</script>

<script class="next-config" data-name="calendar" type="application/json">""</script>
<title>LV16-27-内部Flash-01-基础知识 | 苏木</title>
  








    <script src="/js/browser_tools_disable.js"></script>

  <noscript>
    <link rel="stylesheet" href="/css/noscript.css">
  </noscript>
<!-- hexo injector head_end start --><link rel="stylesheet" href="https://unpkg.com/hexo-next-tags-plus@latest/lib/tag_plus.css" media="defer" onload="this.media='all'"><!-- hexo injector head_end end --></head>

<body itemscope itemtype="http://schema.org/WebPage" class="use-motion">
  <div class="headband"></div>

  <main class="main">
    <div class="column">
      <header class="header" itemscope itemtype="http://schema.org/WPHeader"><div class="site-brand-container">
  <div class="site-nav-toggle">
    <div class="toggle" aria-label="切换导航栏" role="button">
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
        <span class="toggle-line"></span>
    </div>
  </div>

  <div class="site-meta">

    <a href="/" class="brand" rel="start">
      <i class="logo-line"></i>
      <p class="site-title">苏木</p>
      <i class="logo-line"></i>
    </a>
      <p class="site-subtitle" itemprop="description">我的学习之路</p>
  </div>

  <div class="site-nav-right">
    <div class="toggle popup-trigger" aria-label="搜索" role="button">
        <i class="fa fa-search fa-fw fa-lg"></i>
    </div>
  </div>
</div>



<nav class="site-nav">
  <ul class="main-menu menu"><li class="menu-item menu-item-home"><a href="/" rel="section"><i class="fa fa-home fa-fw"></i>苏木的家</a></li><li class="menu-item menu-item-categories"><a href="/categories/" rel="section"><i class="fa fa-th fa-fw"></i>分类页<span class="badge">42</span></a></li><li class="menu-item menu-item-archives"><a href="/archives/" rel="section"><i class="fa fa-archive fa-fw"></i>归档页<span class="badge">673</span></a></li><li class="menu-item menu-item-flink"><a href="/flink/" rel="section"><i class="fa fa-link fa-fw"></i>友人帐</a></li><li class="menu-item menu-item-about"><a href="/about/" rel="section"><i class="fa fa-user fa-fw"></i>关于我</a></li>
      <li class="menu-item menu-item-search">
        <a role="button" class="popup-trigger"><i class="fa fa-search fa-fw"></i>搜索
        </a>
      </li>
  </ul>
</nav>



  <div class="search-pop-overlay">
    <div class="popup search-popup"><div class="search-header">
  <span class="search-icon">
    <i class="fa fa-search"></i>
  </span>
  <div class="search-input-container">
    <input autocomplete="off" autocapitalize="off" maxlength="80"
           placeholder="搜索..." spellcheck="false"
           type="search" class="search-input">
  </div>
  <span class="popup-btn-close" role="button">
    <i class="fa fa-times-circle"></i>
  </span>
</div>
<div class="search-result-container no-result">
  <div class="search-result-icon">
    <i class="fa fa-spinner fa-pulse fa-5x"></i>
  </div>
</div>

    </div>
  </div>

</header>
        
  
  <aside class="sidebar">

    <div class="sidebar-inner sidebar-nav-active sidebar-toc-active">
      <ul class="sidebar-nav">
        <li class="sidebar-nav-toc">
          文章目录
        </li>
        <li class="sidebar-nav-overview">
          站点概览
        </li>
      </ul>

      <div class="sidebar-panel-container">
        <!--noindex-->
        <div class="post-toc-wrap sidebar-panel">
            <div class="post-toc animated"><ol class="nav"><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%80%E3%80%81%E5%86%85%E9%83%A8FLASH"><span class="nav-text">一、内部FLASH</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E7%AE%80%E4%BB%8B"><span class="nav-text">1. 简介</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E8%B5%84%E6%96%99%E6%9F%A5%E6%89%BE"><span class="nav-text">2. 资料查找</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-STM32%E5%86%85%E9%83%A8Flash%E6%A1%86%E5%9B%BE"><span class="nav-text">3. STM32内部Flash框图</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E5%86%85%E9%83%A8FLASH%E6%9E%84%E6%88%90"><span class="nav-text">4. 内部FLASH构成</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#4-1-%E7%BB%84%E6%88%90"><span class="nav-text">4.1 组成</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-2-%E4%B8%BB%E5%AD%98%E5%82%A8%E5%99%A8"><span class="nav-text">4.2 主存储器</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#4-3-%E4%BF%A1%E6%81%AF%E5%9D%97"><span class="nav-text">4.3 信息块</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#3-4-%E6%8E%A5%E5%8F%A3%E5%AF%84%E5%AD%98%E5%99%A8"><span class="nav-text">3.4 接口寄存器</span></a></li></ol></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%BA%8C%E3%80%81FLASH%E7%9B%B8%E5%85%B3%E5%AF%84%E5%AD%98%E5%99%A8"><span class="nav-text">二、FLASH相关寄存器</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-FPEC%E9%94%AE%E5%AF%84%E5%AD%98%E5%99%A8-FLASH-KEYR"><span class="nav-text">1. FPEC键寄存器(FLASH_KEYR) </span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E9%97%AA%E5%AD%98%E6%8E%A7%E5%88%B6%E5%AF%84%E5%AD%98%E5%99%A8-FLASH-CR"><span class="nav-text">2. 闪存控制寄存器(FLASH_CR)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-%E9%97%AA%E5%AD%98%E7%8A%B6%E6%80%81%E5%AF%84%E5%AD%98%E5%99%A8-FLASH-SR"><span class="nav-text">3. 闪存状态寄存器(FLASH_SR)</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E9%97%AA%E5%AD%98%E5%9C%B0%E5%9D%80%E5%AF%84%E5%AD%98%E5%99%A8-FLASH-AR"><span class="nav-text">4. 闪存地址寄存器(FLASH_AR) </span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E4%B8%89%E3%80%81%E9%80%89%E9%A1%B9%E5%AD%97%E8%8A%82%E4%B8%8E%E8%AF%BB%E5%86%99%E4%BF%9D%E6%8A%A4"><span class="nav-text">三、选项字节与读写保护  </span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E9%80%89%E9%A1%B9%E5%AD%97%E8%8A%82%E7%9A%84%E5%86%85%E5%AE%B9"><span class="nav-text">1. 选项字节的内容  </span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#1-1-%E9%80%89%E9%A1%B9%E5%AD%97%E8%8A%82%E7%9A%84%E6%9E%84%E6%88%90"><span class="nav-text">1.1 选项字节的构成</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-2-RDP%E8%AF%BB%E4%BF%9D%E6%8A%A4"><span class="nav-text">1.2 RDP读保护</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-2-1-%E8%AF%BB%E4%BF%9D%E6%8A%A4%E8%AF%B4%E6%98%8E"><span class="nav-text">1.2.1 读保护说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-2-2-%E8%A7%A3%E9%99%A4%E8%AF%BB%E4%BF%9D%E6%8A%A4"><span class="nav-text">1.2.2 解除读保护</span></a></li></ol></li><li class="nav-item nav-level-3"><a class="nav-link" href="#1-3-WRP%E5%86%99%E4%BF%9D%E6%8A%A4"><span class="nav-text">1.3 WRP写保护</span></a><ol class="nav-child"><li class="nav-item nav-level-4"><a class="nav-link" href="#1-3-1-%E5%86%99%E4%BF%9D%E6%8A%A4%E8%AF%B4%E6%98%8E"><span class="nav-text">1.3.1 写保护说明</span></a></li><li class="nav-item nav-level-4"><a class="nav-link" href="#1-3-2-%E8%A7%A3%E9%99%A4%E5%86%99%E4%BF%9D%E6%8A%A4"><span class="nav-text">1.3.2 解除写保护</span></a></li></ol></li></ol></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E4%BF%AE%E6%94%B9%E9%80%89%E9%A1%B9%E5%AD%97%E8%8A%82%E7%9A%84%E8%BF%87%E7%A8%8B"><span class="nav-text">2. 修改选项字节的过程</span></a></li></ol></li><li class="nav-item nav-level-1"><a class="nav-link" href="#%E5%9B%9B%E3%80%81%E5%8F%AF%E8%AF%BB%E5%86%99%E7%A9%BA%E9%97%B4%E8%AE%A1%E7%AE%97"><span class="nav-text">四、可读写空间计算</span></a><ol class="nav-child"><li class="nav-item nav-level-2"><a class="nav-link" href="#1-%E6%95%B4%E4%B8%AA%E5%B7%A5%E7%A8%8B%E7%9A%84%E7%A9%BA%E9%97%B4%E5%88%86%E5%B8%83"><span class="nav-text">1. 整个工程的空间分布</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#2-%E7%A8%8B%E5%BA%8FROM%E7%9A%84%E5%8A%A0%E8%BD%BD%E4%B8%8E%E6%89%A7%E8%A1%8C%E7%A9%BA%E9%97%B4"><span class="nav-text">2. 程序ROM的加载与执行空间</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#3-ROM%E7%A9%BA%E9%97%B4%E5%88%86%E5%B8%83%E8%A1%A8"><span class="nav-text">3. ROM空间分布表</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#4-%E6%88%91%E4%BB%AC%E5%8F%AF%E7%94%A8%E7%A9%BA%E9%97%B4"><span class="nav-text">4.我们可用空间</span></a></li><li class="nav-item nav-level-2"><a class="nav-link" href="#5-%E7%9B%B8%E5%85%B3%E8%AE%A1%E7%AE%97"><span class="nav-text">5. 相关计算</span></a><ol class="nav-child"><li class="nav-item nav-level-3"><a class="nav-link" href="#5-1-%E9%A1%B5%E8%B5%B7%E5%A7%8B%E5%9C%B0%E5%9D%80%E8%AE%A1%E7%AE%97"><span class="nav-text">5.1 页起始地址计算</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-2-%E9%A1%B5%E6%95%B0%E6%80%8E%E4%B9%88%E8%AE%A1%E7%AE%97%EF%BC%9F"><span class="nav-text">5.2 页数怎么计算？</span></a></li><li class="nav-item nav-level-3"><a class="nav-link" href="#5-3-%E4%BB%8E%E5%9C%B0%E5%9D%80%E8%8E%B7%E5%8F%96%E6%98%AF%E7%AC%AC%E5%87%A0%E9%A1%B5"><span class="nav-text">5.3 从地址获取是第几页</span></a></li></ol></li></ol></li></ol></div>
        </div>
        <!--/noindex-->

        <div class="site-overview-wrap sidebar-panel">
          <div class="site-author animated" itemprop="author" itemscope itemtype="http://schema.org/Person">
    <img class="site-author-image" itemprop="image" alt="苏木"
      src="/images/avatar.jpg">
  <p class="site-author-name" itemprop="name">苏木</p>
  <div class="site-description" itemprop="description">莫道桑榆晚，为霞尚满天</div>
</div>
<div class="site-state-wrap animated">
  <nav class="site-state">
      <div class="site-state-item site-state-posts">
        <a href="/archives/">
          <span class="site-state-item-count">673</span>
          <span class="site-state-item-name">日志</span>
        </a>
      </div>
      <div class="site-state-item site-state-categories">
          <a href="/categories/">
        <span class="site-state-item-count">42</span>
        <span class="site-state-item-name">分类</span></a>
      </div>
      <div class="site-state-item site-state-tags">
        <span class="site-state-item-count">43</span>
        <span class="site-state-item-name">标签</span>
      </div>
  </nav>
</div>
  <div class="links-of-author animated">
      <span class="links-of-author-item">
        <a href="https://github.com/sumumm" title="GitHub → https:&#x2F;&#x2F;github.com&#x2F;sumumm" rel="noopener me" target="_blank"><i class="fab fa-github fa-fw"></i>GitHub</a>
      </span>
  </div>

        </div>
      </div>
    </div>

    
  </aside>


    </div>

    <div class="main-inner post posts-expand">


  


<div class="post-block">
  
  

  <article itemscope itemtype="http://schema.org/Article" class="post-content" lang="zh-CN">
    <link itemprop="mainEntityOfPage" href="https://sumumm.github.io/post/37b707ef.html">

    <span hidden itemprop="author" itemscope itemtype="http://schema.org/Person">
      <meta itemprop="image" content="/images/avatar.jpg">
      <meta itemprop="name" content="苏木">
    </span>

    <span hidden itemprop="publisher" itemscope itemtype="http://schema.org/Organization">
      <meta itemprop="name" content="苏木">
      <meta itemprop="description" content="莫道桑榆晚，为霞尚满天">
    </span>

    <span hidden itemprop="post" itemscope itemtype="http://schema.org/CreativeWork">
      <meta itemprop="name" content="LV16-27-内部Flash-01-基础知识 | 苏木">
      <meta itemprop="description" content="">
    </span>
      <header class="post-header">
        <h1 class="post-title" itemprop="name headline">
          LV16-27-内部Flash-01-基础知识
        </h1>

        <div class="post-meta-container">
          <div class="post-meta">
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-calendar"></i>
      </span>
      <span class="post-meta-item-text">发表于</span>

      <time title="创建时间：2023-06-04 22:07:46" itemprop="dateCreated datePublished" datetime="2023-06-04T22:07:46+08:00">2023-06-04</time>
    </span>
    <span class="post-meta-item">
      <span class="post-meta-item-icon">
        <i class="far fa-folder"></i>
      </span>
      <span class="post-meta-item-text">分类于</span>
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">嵌入式开发</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/" itemprop="url" rel="index"><span itemprop="name">01HQ课程体系</span></a>
        </span>
          ，
        <span itemprop="about" itemscope itemtype="http://schema.org/Thing">
          <a href="/categories/%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/" itemprop="url" rel="index"><span itemprop="name">LV16-STM32开发</span></a>
        </span>
    </span>

  
    <span class="post-meta-break"></span>
    <span class="post-meta-item" title="本文字数">
      <span class="post-meta-item-icon">
        <i class="far fa-file-word"></i>
      </span>
      <span class="post-meta-item-text">本文字数：</span>
      <span>8.6k</span>
    </span>
    <span class="post-meta-item" title="阅读时长">
      <span class="post-meta-item-icon">
        <i class="far fa-clock"></i>
      </span>
      <span class="post-meta-item-text">阅读时长 &asymp;</span>
      <span>31 分钟</span>
    </span>
</div>

        </div>
      </header>

    
    
    
    <div class="post-body" itemprop="articleBody"><p>本文主要是STM32开发——内部FLASH基础知识的一些相关笔记，若笔记中有错误或者不合适的地方，欢迎批评指正😃。</p>
<span id="more"></span>

<!-- Photo: https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/ -->

<details class="folding-tag" blue><summary> 点击查看使用工具及版本 </summary>
              <div class='content'>
              <table>    <tr>        <td align="center" width=150px>Windows</td>        <td align="left">windows11</td>    </tr>    <tr>        <td align="center">Ubuntu</td>        <td align="left">Ubuntu16.04的64位版本</td>      </tr>    <tr>        <td align="center">VMware® Workstation 16 Pro</td>        <td align="left">16.2.3 build-19376536</td>      </tr>    <tr>        <td align="center">SecureCRT</td>        <td align="left">Version 8.7.2 (x64 build 2214)   -   正式版-2020年5月14日</td>      </tr>    <tr>        <td align="center">开发板</td>        <td align="left">正点原子 i.MX6ULL Linux阿尔法开发板</td>      </tr>    <tr>        <td align="center">uboot</td>        <td align="left">NXP官方提供的uboot，NXP提供的版本为uboot-imx-rel_imx_4.1.15_2.1.0_ga(使用的uboot版本为U-Boot 2016.03)</td>      </tr>    <tr>        <td align="center">linux内核</td>        <td align="left">linux-4.15(NXP官方提供)</td>      </tr>    <tr>        <td align="center">STM32开发板</td>        <td align="left">正点原子战舰V3(STM32F103ZET6)</td>      </tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看本文参考资料 </summary>
              <div class='content'>
              <ul><li>通用</li></ul><table><tr><td align="center">分类  </td><td align="center">网址</td><td align="center">说明</td></tr><tr><td align="center" rowspan="4">官方网站</td><td align="left"><a href="https://www.arm.com/" target="_blank">https://www.arm.com/</a></td><td align="left">ARM官方网站，在这里我们可以找到Cotex-Mx以及ARMVx的一些文档</td></tr><tr>                                            <td align="left"><a href="https://www.st.com/content/st_com/zh.html" target="_blank">https://www.st.com/content/st_com/zh.html</a></td><td align="left">ST官方网站，在这里我们可以找到STM32的相关文档</td></tr><tr>                                            <td align="left"><a href="https://www.stmcu.com.cn/" target="_blank">https://www.stmcu.com.cn/</a></td><td align="left">意法半导体ST中文官方网站，在这里我们可以找到STM32的相关中文参考文档</td></tr><tr>                                            <td align="left"><a href="http://elm-chan.org/fsw/ff/00index_e.html" target="_blank">http://elm-chan.org/fsw/ff/00index_e.html</a></td><td align="left">FatFs文件系统官网</td></tr><tr><td align="center" rowspan="3">教程书籍</td><td align="left"><a href="STM32开发相关资料/01ARM参考资料/ARM Cortex-M3权威指南(中文).pdf" target="_blank">《ARM Cortex-M3权威指南》</a></td><td alirn="left" rowspan="3">ARM公司专家Joseph Yiu（姚文祥）的力作，中文翻译是NXP的宋岩</td></tr><tr>                                            <td align="left"><a href="STM32开发相关资料/01ARM参考资料/ARM Cortex-M0权威指南(中文).pdf" target="_blank">《ARM Cortex-M0权威指南》</a></td></tr><tr>                                            <td align="left"><a href="" target="_blank">《ARM Cortex-M3与Cortex-M4权威指南》</a></td></tr><tr><td align="center" rowspan="4">开发论坛</td><td align="left"><a href="http://47.111.11.73/forum.php" target="_blank">http://47.111.11.73/forum.php</a></td><td align="left">开源电子网，正点原子的资料下载及问题讨论论坛</td></tr><tr>                                            <td align="left"><a href="https://www.firebbs.cn/forum.php" target="_blank">https://www.firebbs.cn/forum.php</a></td><td align="left">国内Kinetis开发板-野火/秉火（刘火良）主持的论坛，现也做STM32和i.MX RT</td></tr><tr>                                            <td align="left"><a href="https://www.amobbs.com/index.php" target="_blank">https://www.amobbs.com/index.php</a></td><td align="left">阿莫（莫进明）主持的论坛，号称国内最早最火的电子论坛，以交流Atmel AVR系列单片机起家，现已拓展到嵌入式全平台，其STM32系列帖子有70W+。</td></tr><tr>                                            <td align="left"><a href="http://download.100ask.net/index.html" target="_blank">http://download.100ask.net/index.html</a></td><td align="left">韦东山嵌入式资料中心，有些STM32和linux的相关资料也可以来这里找。</td></tr><tr><td align="center" rowspan="3">博客参考</td><td align="left"><a href="http://www.openedv.com/" target="_blank">http://www.openedv.com/</a></td><td align="left">开源网-原子哥个人博客</td></tr><tr>                                            <td align="left"><a href="http://blog.chinaaet.com/jihceng0622" target="_blank">http://blog.chinaaet.com/jihceng0622</a></td><td align="left">博主是原Freescale现NXP的现场应用工程师</td></tr><tr>                                            <td align="left"><a href="https://community.arm.com/arm-community-blogs/b/architectures-and-processors-blog/posts/cortex-m-resources" target="_blank">cortex-m-resources</a></td><td align="left">这其实并不算是一个博客，这是ARM公司专家Joseph Yiu收集整理的所有对开发者有用的官方Cortex-M资料链接（也包含极少数外部资源链接）</td></tr></table><ul><li>STM32</li></ul><table>    <tr><td align="center" rowspan="2">STM32</td><td align="left"><a href="https://doc.embedfire.com/mcu/stm32/f103/hal_general/zh/latest/index.html" target="_blank">STM32 HAL库开发实战指南——基于F103系列开发板</a></td><td align="left">野火STM32开发教程在线文档</td></tr><tr>                                            <td align="left"><a href="https://doc.embedfire.com/mcu/stm32/f103badao/std/zh/latest/index.html" target="_blank">STM32库开发实战指南——基于野火霸道开发板</a></td><td align="left">野火STM32开发教程在线文档</td></tr></table><ul><li>SD卡</li></ul><table>    <tr><td align="left"><a href="https://www.sdcard.org/" target="_blank">SD Association</a></td><td align="left">提供了SD存储卡和SDIO卡系统规范</td></tr></table>
              </div>
            </details>

<details class="folding-tag" blue><summary> 点击查看相关文件下载 </summary>
              <div class='content'>
              <table>    <tr><td align="left"><a href="https://www.st.com/resource/en/datasheet/stm32f103ze.pdf" target="_blank">STM32F103xx英文数据手册</a></td><td align="left">STM32F103xC/D/E系列的英文数据手册</td></tr>    <tr><td align="left"><a href="https://www.stmcu.com.cn/Designresource/detail/localization_document%20/709978" target="_blank">STM32F103xx中文数据手册</a></td><td align="left">STM32F103xC/D/E系列的中文数据手册</td></tr>    <tr><td align="left"><a href="https://www.st.com/resource/en/reference_manual/rm0008-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-armbased-32bit-mcus-stmicroelectronics.pdf" target="_blank">STM32F10xxx英文参考手册（RM0008）</a></td><td align="left">STM32F10xxx系列的英文参考手册</td></tr>    <tr><td align="left"><a href="https://www.stmcu.com.cn/Designresource/detail/localization_document%20/710001" target="_blank">STM32F10xxx中文参考手册（RM0008）</a></td><td align="left">STM32F10xxx系列的中文参考手册</td></tr>    <tr><td align="left"><a href="https://developer.arm.com/documentation/100165/0201/?lang=en" target="_blank">Arm Cortex-M3 处理器技术参考手册-英文版</a></td><td align="left">Cortex-M3技术参考手册-英文版</td></tr>    <tr><td align="left"><a href="https://www.st.com/resource/en/programming_manual/pm0056-stm32f10xxx20xxx21xxxl1xxxx-cortexm3-programming-manual-stmicroelectronics.pdf" target="_blank">STM32F10xxx Cortex-M3编程手册-英文版(PM0056)</a></td><td align="left">STM32F10xxx/20xxx/21xxx/L1xxxx系列Cortex-M3编程手册-英文版</td></tr>    <tr><td align="left"><a href="https://www.sdcard.org/downloads/pls/" target="_blank">SD卡相关资料——最新版本</a></td><td align="left">有关SD卡的一些资料可以从这里下载</td></tr>    <tr><td align="left"><a href="https://www.sdcard.org/downloads/pls/archives/" target="_blank">SD卡相关资料——历史版本</a></td><td align="left">有关SD卡的一些历史版本资料可以从这里下载，比如后边看的SD卡2.0协议</td></tr>    <tr><td align="left"><a href="./" target="_blank">SD 2.0 协议标准完整版</a></td><td align="left">这是一篇关于SD卡2.0协议的中文文档，还是比较有参考价值的，可以一看</td></tr></table>
              </div>
            </details> 

<h1 id="一、内部FLASH"><a href="#一、内部FLASH" class="headerlink" title="一、内部FLASH"></a><font size=3>一、内部FLASH</font></h1><p>这里了解一下内部Flash的一些内容，并不涉及对内部Flash读写等相关操作。</p>
<h2 id="1-简介"><a href="#1-简介" class="headerlink" title="1. 简介"></a><font size=3>1. 简介</font></h2><p>flash是存储芯片的一种，通过特定的程序可以修改里面的数据。FLASH在电子以及半导体领域内往往表示 Flash Memory 的意思，即平时所说的“闪存”，全名叫 Flash EEPROM Memory。它结合了ROM和RAM的长处，不仅具备电子可擦除可编程（EEPROM）的性能，还可以快速读取数据（NVRAM的优势），使数据不会因为断电而丢失。</p>
<p>在STM32芯片内部有一个FLASH存储器，它主要用于存储代码，它是一种nor flash。我们在电脑上编写好应用程序后，使用下载器把编译后的代码文件烧录到该内部FLASH中， 由于FLASH存储器的内容在掉电后不会丢失，芯片重新上电复位后，<strong>内核可从内部FLASH中加载代码并运行</strong>。</p>
<p>除了使用外部的工具（如下载器）读写STM32的内部FLASH外，STM32芯片在运行的时候，也能对自身的内部FLASH进行读写，因此， 若内部FLASH存储了应用程序后还有剩余的空间，我们可以把它像外部SPI-FLASH那样利用起来，<strong>存储一些程序运行时产生的需要掉电保存的数据</strong>。</p>
<p>由于访问内部FLASH的速度要比外部的SPI-FLASH快得多，所以在紧急状态下常常会使用内部FLASH存储关键记录；为了防止应用程序被抄袭， 有的应用会禁止读写内部FLASH中的内容，或者在第一次运行时计算加密信息并记录到某些区域，然后删除自身的部分加密代码，这些应用都涉及到内部FLASH的操作。</p>
<h2 id="2-资料查找"><a href="#2-资料查找" class="headerlink" title="2. 资料查找"></a><font size=3>2. 资料查找</font></h2><p>关于STM32的内部Flash的相关资料是没有在[STM32中文参考手册](<a target="_blank" rel="noopener" href="https://www.stmcu.com.cn/Designresource/detail/localization_document">https://www.stmcu.com.cn/Designresource/detail/localization_document</a> &#x2F;710001)中有所体现的，关于Flash的相关资料，ST官方有另外的文档，叫做STM32F10xxx闪存编程手册，英文版在这里：<a target="_blank" rel="noopener" href="https://www.st.com/resource/en/programming_manual/pm0075-stm32f10xxx-flash-memory-microcontrollers-stmicroelectronics.pdf">STM32F10xxx Flash memory microcontrollers</a>，这个手册也有中文版，但是我在中文社区没找到，那就看个本地版的吧：<a href="STM32%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/04STM32%E8%B5%84%E6%96%99/STM32F10xxx%E9%97%AA%E5%AD%98%E7%BC%96%E7%A8%8B%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C.pdf">STM32F10xxx闪存编程参考手册</a></p>
<h2 id="3-STM32内部Flash框图"><a href="#3-STM32内部Flash框图" class="headerlink" title="3. STM32内部Flash框图"></a><font size=3>3. STM32内部Flash框图</font></h2><p>我们可以看一下[STM32中文参考手册](<a target="_blank" rel="noopener" href="https://www.stmcu.com.cn/Designresource/detail/localization_document">https://www.stmcu.com.cn/Designresource/detail/localization_document</a> &#x2F;710001)的2.1 系统构架：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530174140633.png" alt="image-20230530174140633" style="zoom:50%;" />

<p>除了使用外部的工具（如下载器）读写内部 FLASH 外， STM32 芯片在运行的时候，也能对自身的内部 FLASH 进行读写，因此，若内部 FLASH 存储了应用程序后还有剩余的空间，我们可以把它像外部 SPI-FLASH 那样利用起来，存储一些程序运行时产生的需要掉电保存的数据。</p>
<p>由于访问内部 FLASH 的速度要比外部的 SPI-FLASH 快得多，所以在紧急状态下常常会使用内部FLASH 存储关键记录；为了防止应用程序被抄袭，有的应用会禁止读写内部 FLASH 中的内容，或者在第一次运行时计算加密信息并记录到某些区域，然后删除自身的部分加密代码，这些应用都涉及到内部 FLASH 的操作。  </p>
<h2 id="4-内部FLASH构成"><a href="#4-内部FLASH构成" class="headerlink" title="4. 内部FLASH构成"></a><font size=3>4. 内部FLASH构成</font></h2><h3 id="4-1-组成"><a href="#4-1-组成" class="headerlink" title="4.1 组成"></a><font size=3>4.1 组成</font></h3><p>STM32 的内部FLASH（闪存模块）由：<strong>主存储器</strong>、<strong>信息块</strong>和<strong>闪存存储器接口寄存器</strong>等 3 部分组成。  这一部分的相关说明我们需要查看<a href="STM32%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/04STM32%E8%B5%84%E6%96%99/STM32F10xxx%E9%97%AA%E5%AD%98%E7%BC%96%E7%A8%8B%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C.pdf">STM32F10xxx闪存编程参考手册</a>，这个中文版本的1.2 闪存模块组织，也有英文版本的（<a target="_blank" rel="noopener" href="https://www.st.com/resource/en/programming_manual/pm0075-stm32f10xxx-flash-memory-microcontrollers-stmicroelectronics.pdf">STM32F10xxx Flash memory microcontrollers</a>），其实在[STM32中文参考手册](<a target="_blank" rel="noopener" href="https://www.stmcu.com.cn/Designresource/detail/localization_document">https://www.stmcu.com.cn/Designresource/detail/localization_document</a> &#x2F;710001)的2.3.3 嵌入式闪存这一节也有这个表。在ST官网上可以找到相应的英文版本。如下图为STM32F1系列芯片大容量产品的闪存模块组织图：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530135945546.png" alt="image-20230530135945546" style="zoom:50%;" />

<p>注意上表中的主存储器是本实验板使用的 STM32F103ZET6 型号芯片的参数，即 STM32F1 大容量产品。若使用超大容量、中容量或小容量产品，它们主存储器的页数量、页大小均有不同，使用的时候要注意区分。  </p>
<p>需要知道的是主存储器和信息块的写入，由内嵌的闪存编程&#x2F;擦除控制器(FPEC)管理，编程与擦除的高电压由内部产生。在执行闪存写操作时，任何对闪存的读操作都会锁住总线，在写操作完成后读操作才能正确地进行，即在进行写或擦除操作时，不能进行代码或数据的读取操作。 </p>
<h3 id="4-2-主存储器"><a href="#4-2-主存储器" class="headerlink" title="4.2 主存储器"></a><font size=3>4.2 主存储器</font></h3><p>一般我们说STM32内部FLASH的时候，都是指这个主存储器区域（主闪存存储器），它是<strong>存储用户应用程序的空间</strong>， 芯片型号说明中的256K FLASH、512K FLASH都是指这个区域的大小。</p>
<p>对于STM32F103ZET6型号芯片，主存储器分为<strong>256页，每页大小为2KB，共512KB</strong>。这个分页的概念，实质就是FLASH存储器的扇区，与其它FLASH一样，在写入数据前，要先按页（扇区）擦除。从上图可以看出主存储器的起始地址就是 0X08000000，当启动引脚BOOT0为低电平时，系统将从0x08000000地址开始读取代码，也就是从<br>主存储器（ Main Flash memory）启动。  </p>
<p><strong>【注意】</strong>上表中的主存储器是STM32F103ZET6型号芯片的参数，芯片型号中的E就表示这是STM32F1系列的大容量产品，并且容量为512KB。若使用超大容量、中容量或小容量产品， 它们主存储器的页数量、页大小均有不同，使用的时候要注意区分。芯片型号各部分代表的含义其实可以查看芯片手册的《7 Part numbering  》这一节，在芯片手册上有对芯片型号的详细说明。</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530140426886.png" alt="image-20230530140426886" style="zoom:50%;" />

<h3 id="4-3-信息块"><a href="#4-3-信息块" class="headerlink" title="4.3 信息块"></a><font size=3>4.3 信息块</font></h3><p>该部分分为 2 个小部分，分别是启动程序代码和用户选择字节。</p>
<p>（1）系统存储器：这部分是用来存储 ST 芯片出厂时已经固化了的启动代码，用于实现串口、USB以及CAN等ISP烧录功能。这个也可以叫系统存储器，都是一个意思，<a target="_blank" rel="noopener" href="https://www.st.com/resource/en/programming_manual/pm0075-stm32f10xxx-flash-memory-microcontrollers-stmicroelectronics.pdf">STM32F10xxx Flash memory microcontrollers</a>的1.2 Flash module organization一节中，这个地方是叫system memory，个人觉得还是叫系统存储器更符合原版手册。当启动引脚BOOT0为高电平， BOOT1为低电平时， 系统将从0x1FFFF000地址开始读取代码， 该代码将从UART收到的数据写到主存储器。也就是通过UART实现程序的下载。  </p>
<p>（2）选项字节：用于配置FLASH的读写保护、待机&#x2F;停机复位、软件&#x2F;硬件看门狗等功能，这部分共16字节。可以通过修改FLASH的选项控制寄存器修改。</p>
<h3 id="3-4-接口寄存器"><a href="#3-4-接口寄存器" class="headerlink" title="3.4 接口寄存器"></a><font size=3>3.4 接口寄存器</font></h3><p>闪存存储器接口寄存器，该部分用于控制闪存读写等，是整个闪存模块的控制机构。  这部分其实就包含了STM32的 FPEC（闪存编程和擦除控制器）模块，我们对FLASH的操作就是通过这个模块来实现的，这个模块包含了 7 个32位寄存器，分别是：</p>
<table>
<thead>
<tr>
<th>寄存器名称</th>
<th>地址</th>
<th>说明</th>
</tr>
</thead>
<tbody><tr>
<td>FLASH_KEYR</td>
<td>0x4002_2004 – 0x4002_2007</td>
<td>FPEC 键寄存器</td>
</tr>
<tr>
<td>FLASH_OPTKEYR</td>
<td>0x4002_2008 – 0x4002_200B</td>
<td>选择字节键寄存器</td>
</tr>
<tr>
<td>FLASH_SR</td>
<td>0x4002_200C – 0x4002_200F</td>
<td>闪存状态寄存器</td>
</tr>
<tr>
<td>FLASH_CR</td>
<td>0x4002_2010 – 0x4002_2013</td>
<td>闪存控制寄存器</td>
</tr>
<tr>
<td>FLASH_AR</td>
<td>0x4002_2014 – 0x4002_2017</td>
<td>闪存地址寄存器</td>
</tr>
<tr>
<td>FLASH_OBR</td>
<td>0x4002_201C – 0x4002_201F</td>
<td>选择字节寄存器</td>
</tr>
<tr>
<td>FLASH_WRPR</td>
<td>0x4002_2020 – 0x4002_2023</td>
<td>写保护寄存器</td>
</tr>
</tbody></table>
<p>【说明】其中FPEC总共有3个键值：RDPRT键&#x3D;0X000000A5；KEY1&#x3D;0X45670123；KEY2&#x3D;0XCDEF89AB</p>
<h1 id="二、FLASH相关寄存器"><a href="#二、FLASH相关寄存器" class="headerlink" title="二、FLASH相关寄存器"></a><font size=3>二、FLASH相关寄存器</font></h1><p>这一部分我们就需要参考<a href="STM32%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/04STM32%E8%B5%84%E6%96%99/STM32F10xxx%E9%97%AA%E5%AD%98%E7%BC%96%E7%A8%8B%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C.pdf">STM32F10xxx闪存编程参考手册</a>的3 寄存器说明啦。这里只简单介绍几个，主要我们还是用库函数操作，这里简单了解下。</p>
<h2 id="1-FPEC键寄存器-FLASH-KEYR"><a href="#1-FPEC键寄存器-FLASH-KEYR" class="headerlink" title="1. FPEC键寄存器(FLASH_KEYR) "></a><font size=3>1. FPEC键寄存器(FLASH_KEYR) </font></h2><img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530174859848.png" alt="image-20230530174859848" style="zoom: 80%;" />

<p>该寄存器主要用来解锁 FPEC，必须在该寄存器写入特定的序列（KEY1 和 KEY2）解锁后，才能对 FLASH_CR 寄存器进行写操作。  </p>
<h2 id="2-闪存控制寄存器-FLASH-CR"><a href="#2-闪存控制寄存器-FLASH-CR" class="headerlink" title="2. 闪存控制寄存器(FLASH_CR)"></a><font size=3>2. 闪存控制寄存器(FLASH_CR)</font></h2><img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175141413.png" alt="image-20230530175141413" style="zoom:80%;" />

<p>（1）LOCK 位，该位用于指示 FLASH_CR 寄存器是否被锁住，该位在检测到正确的解锁序列后，硬件将其清零。在一次不成功的解锁操作后，在下次系统复位之前，该位将不再改变。</p>
<p>（2）STRT 位，该位用于开始一次擦除操作。在该位写入 1 ，将执行一次擦除操作。</p>
<p>（3）PER 位，该位用于选择页擦除操作，在页擦除的时候，需要将该位置 1。</p>
<p>（4）PG 位，该位用于选择编程操作，在往 FLASH 写数据的时候，该位需要置 1。  </p>
<p>其他的位可以看参考手册。</p>
<h2 id="3-闪存状态寄存器-FLASH-SR"><a href="#3-闪存状态寄存器-FLASH-SR" class="headerlink" title="3. 闪存状态寄存器(FLASH_SR)"></a><font size=3>3. 闪存状态寄存器(FLASH_SR)</font></h2><img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175015147.png" alt="image-20230530175015147" style="zoom:80%;" />

<p>该寄存器主要用来指示当前 FPEC 的操作编程状态。  各位描述如下：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175249232.png" alt="image-20230530175249232" style="zoom: 50%;" />

<h2 id="4-闪存地址寄存器-FLASH-AR"><a href="#4-闪存地址寄存器-FLASH-AR" class="headerlink" title="4. 闪存地址寄存器(FLASH_AR) "></a><font size=3>4. 闪存地址寄存器(FLASH_AR) </font></h2><img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230530175343778.png" alt="image-20230530175343778" style="zoom: 50%;" />

<p>这些位由硬件修改为当前&#x2F;最后使用的地址。在页擦除操作中，软件必须修改这个寄存器以指定要擦除的页。</p>
<p>FAR：闪存地址 当进行编程时选择要编程的地址，当进行页擦除时选择要擦除的页。 注意：当FLASH_SR中的BSY位为’1’时，不能写这个寄存器。</p>
<h1 id="三、选项字节与读写保护"><a href="#三、选项字节与读写保护" class="headerlink" title="三、选项字节与读写保护  "></a><font size=3>三、选项字节与读写保护  </font></h1><p>在实际发布的产品中，在 STM32 芯片的内部 FLASH 存储了控制程序，如果不作任何保护措施的话，可以使用下载器直接把内部 FLASH 的内容读取回来，得到 bin 或 hex 文件格式的代码拷贝，别有用心的厂商会利用该方法山寨产品。为此， STM32 芯片提供了多种方式保护内部 FLASH 的程序不被非法读取，但在默认情况下该保护功能是不开启的，若要开启该功能，需要改写内部FLASH 选项字节 (Option Bytes) 中的配置。  </p>
<h2 id="1-选项字节的内容"><a href="#1-选项字节的内容" class="headerlink" title="1. 选项字节的内容  "></a><font size=3>1. 选项字节的内容  </font></h2><h3 id="1-1-选项字节的构成"><a href="#1-1-选项字节的构成" class="headerlink" title="1.1 选项字节的构成"></a><font size=3>1.1 选项字节的构成</font></h3><p>选项字节是一段特殊的 FLASH 空间， STM32 芯片会根据它的内容进行读写保护配置，选项字节的构成见下表，可以参考<a href="STM32%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/04STM32%E8%B5%84%E6%96%99/STM32F10xxx%E9%97%AA%E5%AD%98%E7%BC%96%E7%A8%8B%E5%8F%82%E8%80%83%E6%89%8B%E5%86%8C.pdf">STM32F10xxx闪存编程参考手册</a>的2.5 选择字节说明：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531095555140.png" alt="image-20230531095555140" style="zoom:50%;" />

<p>STM32F103 系列芯片的选项字节有 8 个配置项，即上表中的 USER、 RDP、 DATA0&#x2F;1 及 WRP0&#x2F;1&#x2F;2&#x2F;3，而表中带 n 的同类项是该项的反码，即 nUSER 的值等于 (<del>USER)、 nRDP 的值等于 (</del>RDP)， STM32利用反码来确保选项字节内容的正确性。  选项字节的 8 个配置项具体的数据位配置说明如下</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531100044334.png" alt="image-20230531100044334" style="zoom:67%;" />

<p>我们主要学习选项字节配置中的 RDP 位和 WRPx 位，它们分别用于配置读保护和写保护。  </p>
<h3 id="1-2-RDP读保护"><a href="#1-2-RDP读保护" class="headerlink" title="1.2 RDP读保护"></a><font size=3>1.2 RDP读保护</font></h3><h4 id="1-2-1-读保护说明"><a href="#1-2-1-读保护说明" class="headerlink" title="1.2.1 读保护说明"></a><font size=3>1.2.1 读保护说明</font></h4><p>修改选项字节的 RDP 位的值可设置内部 FLASH 为以下保护级别：  </p>
<p>（1）0xA5：无保护，这是 STM32 的默认保护级别，它没有任何读保护，读取内部 FLASH 的内容都没有任何限制。也就是说，第三方可以使用调试器等工具，获取该芯片 FLASH 中存储的程序，然后可以把获得的程序以 bin 和 hex 的格式下载到另一块 STM32 芯片中，加上PCB 抄板技术，轻易复制出同样的产品。  </p>
<p>（2）其它值：使能读保护 ，把 RDP 配置成除 0xA5 外的任意数值，都会使能读保护。在这种情况下，若使用调试功能 (使用下载器、仿真器) 或者从内部 SRAM 自举时都不能对内部 FLASH 作任何访问 (读写、擦除都被禁止)；而如果 STM32 是从内部 FLASH 自举时，它允许对内部FLASH 的任意访问。也就是说，任何尝试从外部访问内部 FLASH 内容的操作都被禁止。例如，无法通过下载器读取它的内容，或编写一个从内部 SRAM 启动的程序，若该 SRAM 启动的程序读取内部 FLASH，会被禁止。而如果是芯片原本的内部 FLASH程序自己访问内部 FLASH（即从 FLASH 自举的程序），是完全没有问题的，例如芯片本身的程序，若包含有指针对内部 FLASH 某个地址进行的读取操作，它能获取正常的数据。  </p>
<p>另外，被设置成读保护后， FLASH 前 4K 字节的空间会强制加上写保护，也就是说，即使是从 FLASH 启动的程序，也无法擦写这 4K 字节空间的内容；而对于前 4K 字节以外的空间，读保护并不影响它对其它空间的擦除&#x2F;写入操作。利用这个特性，可以编写 IAP 代码 (In Application Program) 更新 FLASH 中的程序，它的原理是通过某个通讯接口获取将要更新的程序内容，然后利用内部 FLASH 擦写操作把这些内容烧录到自己的内部 FLASH 中，实现应用程序的更新，该原理类似串口 ISP 程序下载功能，只不过 ISP 这个接收数据并更新的代码由 ST 提供，且存放在系统存储区域，而 IAP 是由用户自行编写的，存放在用户自定义的 FLASH 区域，且通讯方式可根据用户自身的需求定制，如 IIC、 SPI 等，只要能接收到数据均可。</p>
<p> 芯片被配置成读保护后根据不同的使用情况，访问权限不同，如下表：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531100517228.png" alt="image-20230531100517228" style="zoom:50%;" />

<h4 id="1-2-2-解除读保护"><a href="#1-2-2-解除读保护" class="headerlink" title="1.2.2 解除读保护"></a><font size=3>1.2.2 解除读保护</font></h4><p>当需要解除芯片的读保护时，要把选项字节的 RDP 位重新设置为 0xA5。在解除保护前，芯片会自动触发擦除主 FLASH 存储器的全部内容，即解除保护后原内部 FLASH的代码会丢失，从而防止降级后原内容被读取到。 </p>
<h3 id="1-3-WRP写保护"><a href="#1-3-WRP写保护" class="headerlink" title="1.3 WRP写保护"></a><font size=3>1.3 WRP写保护</font></h3><h4 id="1-3-1-写保护说明"><a href="#1-3-1-写保护说明" class="headerlink" title="1.3.1 写保护说明"></a><font size=3>1.3.1 写保护说明</font></h4><p>使用选项字节的 WRP0&#x2F;1&#x2F;2&#x2F;3 可以设置主 FLASH 的写保护，防止它存储的程序内容被修改。写保护的配置一般以 4K 字节为单位，除 WRP3 的最后一位比较特殊外，每个 WRP选项字节的一位用于控制 4K 字节的写访问权限，把对应 WRP 的位置 0 即可把它匹配的空间加入写保护。被设置成写保护后，主 FLASH 中的内容使用任何方式都不能被擦除和写入，写保护不会影响读访问权限，读访问权限完全由前面介绍的读保护设置限制 。</p>
<p>对于大容量产品，选择字节WRPx中的每一个比特位用于保护主存储器中2个存储页(2K字节&#x2F; 页)，但是WRP3的位7用于保护第62<del>255页。WRP0：第0</del>15页的写保护，WRP1：第16<del>31页的写保护，WRP2：第32</del>47页的写保护，WRP3：位0<del>6提供第48</del>61页的写保护，位7提供第62~255页的写保护。</p>
<h4 id="1-3-2-解除写保护"><a href="#1-3-2-解除写保护" class="headerlink" title="1.3.2 解除写保护"></a><font size=3>1.3.2 解除写保护</font></h4><p>解除写保护是逆过程，把对应 WRP 的位置 1 即可把它匹配的空间解除写保护。解除写保护后，主 FLASH 中的内容不会像解读保护那样丢失，它会被原样保留。  </p>
<h2 id="2-修改选项字节的过程"><a href="#2-修改选项字节的过程" class="headerlink" title="2. 修改选项字节的过程"></a><font size=3>2. 修改选项字节的过程</font></h2><p>修改选项字节的内容可修改读写保护配置，不过选项字节复位后的默认状态是始终可以读但被写保护的，因此它具有类似前面提到的 FLASH_CR 寄存器的访问限制，要想修改，需要先对 FLASH_OPTKEYR 寄存器写入解锁编码。由于修改选项字节时也需要访问 FLASH_CR 寄存器，所以同样也要对 FLASH_KEYR 写入解锁编码。修改选项字节的整个过程总结如下：</p>
<ul>
<li>1、解除 FLASH_CR 寄存器的访问限制</li>
</ul>
<p>（1）往 FPEC 键寄存器 FLASH_KEYR 中写入 KEY1 &#x3D; 0x45670123</p>
<p>（2）再往 FPEC 键寄存器 FLASH_KEYR 中写入 KEY2 &#x3D; 0xCDEF89AB</p>
<ul>
<li>2、解除对选项字节的访问限制</li>
</ul>
<p>（1）往 FLASH_OPTKEYR 中写入 KEY1 &#x3D; 0x45670123</p>
<p>（2）再往 FLASH_OPTKEYR 中写入 KEY2 &#x3D; 0xCDEF89AB  </p>
<ul>
<li><p>3、配置 FLASH_CR 的 OPTPG 位，准备修改选项字节</p>
</li>
<li><p>4、直接使用指针操作修改选项字节的内容，根据需要修改 RDP、 WRP 等内容</p>
</li>
<li><p>5、对于读保护的解除，由于它会擦除 FLASH 的内容，所以需要检测状态寄存器标志位以确认FLASH 擦除操作完成。</p>
</li>
<li><p>6、若是设置读保护及其解除，需要给芯片重新上电复位，以使新配置的选项字节生效；对于设置写保护及其解除，需要给芯片进行系统复位，以使新配置的选项字节生效。</p>
</li>
</ul>
<h1 id="四、可读写空间计算"><a href="#四、可读写空间计算" class="headerlink" title="四、可读写空间计算"></a><font size=3>四、可读写空间计算</font></h1><p>其实我们读写FLASH的时候会有问题的，因为我们写好的代码也是保存在FLASH中的，万一我们不小心擦除了我们的代码存储区域，这不就完了，那怎么确保我们要进行读写的FLASH地址空间不会跟我们程序使用的FLASH区域产生冲突呢？下边就一起来了解一下把。</p>
<h2 id="1-整个工程的空间分布"><a href="#1-整个工程的空间分布" class="headerlink" title="1. 整个工程的空间分布"></a><font size=3>1. 整个工程的空间分布</font></h2><p>在使用内部FLASH存储其它数据前需要了解哪一些空间已经写入了程序代码，存储了程序代码的扇区都不应作任何修改。 通过查询应用程序编译时产的 .map 后缀文件，可以了解程序存储到了哪些区域， 我们可以到工程目录中的 Listing 文件夹中找到，也可以通过下图提示找到：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531075735423.png" alt="image-20230531075735423" style="zoom:67%;" />

<p>打开map文件后，查看文件最后部分的区域，可以看到一段以 Memory Map of the image 开头的记录：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br></pre></td><td class="code"><pre><span class="line">==============================================================================</span><br><span class="line"></span><br><span class="line">Memory Map of the image  <span class="comment">//存储分布映像</span></span><br><span class="line"></span><br><span class="line">  Image Entry point : <span class="number">0x08000131</span></span><br><span class="line">  <span class="comment">/* 程序 ROM 加载空间 */</span></span><br><span class="line">  Load Region LR_IROM1 (Base: <span class="number">0x08000000</span>, Size: <span class="number">0x00000a38</span>, Max: <span class="number">0x00080000</span>, ABSOLUTE, COMPRESSED[<span class="number">0x00000648</span>])</span><br><span class="line">    <span class="comment">/* 程序 ROM 执行空间 */</span></span><br><span class="line">    Execution Region ER_IROM1 (Exec base: <span class="number">0x08000000</span>, Load base: <span class="number">0x08000000</span>, Size: <span class="number">0x00000638</span>, Max: <span class="number">0x00080000</span>, ABSOLUTE)</span><br><span class="line">	<span class="comment">/* 地址分布列表 */</span></span><br><span class="line">    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object</span><br><span class="line"></span><br><span class="line">    <span class="number">0x08000000</span>   <span class="number">0x08000000</span>   <span class="number">0x00000130</span>   Data   RO            <span class="number">3</span>    RESET               startup_stm32f10x_hd.o</span><br><span class="line">    <span class="number">0x08000130</span>   <span class="number">0x08000130</span>   <span class="number">0x00000000</span>   Code   RO         <span class="number">3210</span>  * .ARM.Collect$$$$<span class="number">00000000</span>  mc_w.l(entry.o)</span><br><span class="line"><span class="comment">// 中间部分省略......</span></span><br><span class="line">      </span><br><span class="line">    Execution Region RW_IRAM1 (Exec base: <span class="number">0x20000000</span>, Load base: <span class="number">0x08000638</span>, Size: <span class="number">0x00000800</span>, Max: <span class="number">0x00010000</span>, ABSOLUTE, COMPRESSED[<span class="number">0x00000010</span>])</span><br><span class="line"></span><br><span class="line">    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object</span><br><span class="line"></span><br><span class="line">    <span class="number">0x20000000</span>   COMPRESSED   <span class="number">0x00000400</span>   Data   RW         <span class="number">3110</span>    .data               main.o</span><br><span class="line">    <span class="number">0x20000400</span>        -       <span class="number">0x00000400</span>   Zero   RW            <span class="number">1</span>    STACK               startup_stm32f10x_hd.o</span><br><span class="line"></span><br><span class="line"></span><br><span class="line">==============================================================================</span><br></pre></td></tr></table></figure>

<p>这一段是就是之前分析MDK工程文件使用的<a href="STM32%E5%BC%80%E5%8F%91%E7%9B%B8%E5%85%B3%E8%B5%84%E6%96%99/03MDK/%E7%A8%8B%E5%BA%8F/MDK%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3-GPIO%E8%BE%93%E5%87%BA%E2%80%94%E5%A4%9A%E5%BD%A9%E6%B5%81%E6%B0%B4%E7%81%AF/Project/RVMDK%EF%BC%88uv5%EF%BC%89/BH-F103.uvprojx">流水灯工程</a>的 ROM 存储器分布映像，在 STM32 芯片中， ROM 区域的内容就是指存储到内部 FLASH 的代码。  其中 Memory Map of the image 表示这是存储分布映像部分。</p>
<h2 id="2-程序ROM的加载与执行空间"><a href="#2-程序ROM的加载与执行空间" class="headerlink" title="2. 程序ROM的加载与执行空间"></a><font size=3>2. 程序ROM的加载与执行空间</font></h2><p>前边我们打开的 map 文件中中有两段分别以“Load Region LR_ROM1”及“Execution Region ER_IROM1”开头的内容：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20230531080159961.png" alt="image-20230531080159961" style="zoom:50%;" />

<p>Load Region LR_ROM1 描述的是程序的加载空间，Execution Region ER_IROM1 描述的是程序的执行空间。在芯片刚上电运行时，会加载程序及数据。例如，它会从程序的存储区域加载到程序的执行区域，还把一些已初始化的全局变量从 ROM 复制到 RAM 空间， 以便程序运行时可以修改变量的内容。加载完成后，程序开始从执行区域开始执行。</p>
<p>在上面 map 文件的描述中，我们了解到加载及执行空间的基地址(Base)都是 0x08000000 ，它正好是STM32内部FLASH的首地址， 即STM32的<strong>程序存储空间就直接是执行空间</strong>；它们的大小(Size)分别为 0x00000638 及 0x00000a38 ，我们会发现执行空间的大小比加载空间的大小要小，执行空间的ROM比较小的原因就是因为部分 RW-data 类型的变量被拷贝到 RAM 空间了； 它们的最大空间(Max)均为0x00080000，即 512K 字节，它指的是内部FLASH的最大空间。</p>
<p>计算程序占用的空间时，需要<strong>使用加载区域的大小进行计算</strong>，本例子中应用程序使用的内部FLASH是从 0x08000000 至( 0x08000000 + 0x00000a38 )地址的空间区域。</p>
<h2 id="3-ROM空间分布表"><a href="#3-ROM空间分布表" class="headerlink" title="3. ROM空间分布表"></a><font size=3>3. ROM空间分布表</font></h2><p>在加载及执行空间总体描述之后，紧接着一个 ROM 详细地址分布表，它列出了工程中的各个段(如函数、常量数据)所在的地址BaseAddr 及占用的空间 Size：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">	<span class="comment">/* 地址分布列表 */</span></span><br><span class="line">    Exec Addr    Load Addr    Size         Type   Attr      Idx    E Section Name        Object</span><br><span class="line"></span><br><span class="line">    <span class="number">0x08000000</span>   <span class="number">0x08000000</span>   <span class="number">0x00000130</span>   Data   RO            <span class="number">3</span>    RESET               startup_stm32f10x_hd.o</span><br><span class="line">    <span class="number">0x08000130</span>   <span class="number">0x08000130</span>   <span class="number">0x00000000</span>   Code   RO         <span class="number">3210</span>  * .ARM.Collect$$$$<span class="number">00000000</span>  mc_w.l(entry.o)</span><br><span class="line"><span class="comment">// 中间部分省略......</span></span><br><span class="line">    <span class="number">0x080004f6</span>   <span class="number">0x080004f6</span>   <span class="number">0x00000002</span>   PAD</span><br><span class="line">    <span class="number">0x080004f8</span>   <span class="number">0x080004f8</span>   <span class="number">0x00000120</span>   Code   RO         <span class="number">3109</span>    i.main              main.o</span><br><span class="line">    <span class="number">0x08000618</span>   <span class="number">0x08000618</span>   <span class="number">0x00000020</span>   Data   RO         <span class="number">3229</span>    Region$$Table       anon$$obj.o</span><br></pre></td></tr></table></figure>

<p>列表中的 Type说明了该段的类型，CODE表示代码，DATA表示数据，而PAD表示段之间的填充区域，它是无效的内容， PAD区域往往是为了解决地址对齐的问题。观察表中的最后一项，它的基地址是 0x08007398 ，大小为 0x00000020 ，可知它占用的最高的地址空间为:</p>
<figure class="highlight shell"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">0x08000618  + 0x00000020 = 0x08000638</span><br></pre></td></tr></table></figure>

<p>我们发现跟执行区域的最高地址 0x08000638 一样， 但它们比加载区域说明中的最高地址 0x00000a38 要小，所以我们<strong>以加载区域的大小为准</strong>。</p>
<h2 id="4-我们可用空间"><a href="#4-我们可用空间" class="headerlink" title="4.我们可用空间"></a><font size=3>4.我们可用空间</font></h2><p>经过上边的分析，我们知道了从 0x08000000 开始，0x00000a38 大小的区域存储了我们的应用程序，我们计算一下这大概就是 2616 字节的数据，一共就是 2.55 KB，而在我们的FLASH中，每一页是 2 KB，所以说，此应用程序将会占用 2 页（4KB）。对比STM32大容量产品内部FLASH的构成的内部FLASH页地址分布表：</p>
<img data-src="https://fanhua-picture.oss-cn-hangzhou.aliyuncs.com/01%E5%B5%8C%E5%85%A5%E5%BC%8F%E5%BC%80%E5%8F%91/01HQ%E8%AF%BE%E7%A8%8B%E4%BD%93%E7%B3%BB/LV16-STM32%E5%BC%80%E5%8F%91/LV16-27-%E5%86%85%E9%83%A8Flash-01-%E5%9F%BA%E7%A1%80%E7%9F%A5%E8%AF%86/img/image-20220924210401860.png" alt="image-20220924210401860" style="zoom:50%;" />

<p>我们可以知道可知使用 页 0 至 页 3 就可以完全存储本应用程序，所以从页 4后的存储空间都可以作其它用途，使用这些存储空间时不会篡改应用程序空间的数据。</p>
<h2 id="5-相关计算"><a href="#5-相关计算" class="headerlink" title="5. 相关计算"></a><font size=3>5. 相关计算</font></h2><h3 id="5-1-页起始地址计算"><a href="#5-1-页起始地址计算" class="headerlink" title="5.1 页起始地址计算"></a><font size=3>5.1 页起始地址计算</font></h3><p>比如说，页4地址怎么计算？</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">page_addr = <span class="number">0x0800</span> <span class="number">0000</span> + <span class="number">0x800</span> * num</span><br></pre></td></tr></table></figure>

<p>比如页2的起始地址就等于0x0800 0000 + 0x800 x 2 &#x3D; 0x0800 1000。</p>
<h3 id="5-2-页数怎么计算？"><a href="#5-2-页数怎么计算？" class="headerlink" title="5.2 页数怎么计算？"></a><font size=3>5.2 页数怎么计算？</font></h3><p>假设我们现在要写入7000个字节的数据，那么它需要占多少页呢？我们直接对2048取模就可以得到整数页，但是可能还会有余数，这些也是要占一整个页面的，所以只要余数不是0，都需要再增加一个页，所以计算方式就是：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">page_count = (len / sector_size) + ((len % sector_size)?<span class="number">1</span>:<span class="number">0</span>)</span><br></pre></td></tr></table></figure>

<p>比如刚才的7000字节：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">page_count = (<span class="number">7000</span> / <span class="number">2048</span>) + ((<span class="number">7000</span> % <span class="number">2048</span>)?<span class="number">1</span>:<span class="number">0</span>) = <span class="number">3</span> + (<span class="number">0.42</span>?<span class="number">1</span>:<span class="number">0</span>) = <span class="number">3</span> + <span class="number">1</span> = <span class="number">4</span></span><br></pre></td></tr></table></figure>

<h3 id="5-3-从地址获取是第几页"><a href="#5-3-从地址获取是第几页" class="headerlink" title="5.3 从地址获取是第几页"></a><font size=3>5.3 从地址获取是第几页</font></h3><p>我们要是从指定地址开始写数据，那么这个地址是属于第几页？我们可以这样来计算：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">page_num = (addr - <span class="number">0x0800</span> <span class="number">0000</span>)/sector_size <span class="comment">// 取整数部分即可</span></span><br></pre></td></tr></table></figure>

<p>比如0x08001900是第几页？我们带入上边的计算公式，可以得到：</p>
<figure class="highlight c"><table><tr><td class="gutter"><pre><span class="line">1</span><br></pre></td><td class="code"><pre><span class="line">page_num = (<span class="number">0x0800</span> <span class="number">1900</span> - <span class="number">0x0800</span> <span class="number">0000</span>)/<span class="number">2048</span> = <span class="number">3</span></span><br></pre></td></tr></table></figure>

<p>这样我们就得到是第三页啦。</p>

    </div>

    
    
    

    <footer class="post-footer">




    <div>
        
            <div style="text-align:center;color: #ccc;font-size:14px;">
            ----------本文结束
            <i class="fas fa-fan fa-spin" style="color: #FF1493; font-size: 1rem"></i>
            感谢您的阅读----------
            </div>
        
    </div>





  
  <div class="my_post_copyright"> 
    <p><span>文章标题:</span><a href="/post/37b707ef.html">LV16-27-内部Flash-01-基础知识</a></p>
    <p><span>文章作者:</span><a href="/" title="欢迎访问 《苏木》 的学习笔记">苏木</a></p>
    <p><span>发布时间:</span>2023年06月04日 - 22:07</p>
    <p><span>最后更新:</span>2025年06月14日 - 00:25</p>
    <p><span>原始链接:</span><a href="/post/37b707ef.html" title="LV16-27-内部Flash-01-基础知识">https://sumumm.github.io/post/37b707ef.html</a></p>
    <p><span>许可协议:</span><i class="fab fa-creative-commons"></i> <a rel="license" href= "https://creativecommons.org/licenses/by-nc-nd/4.0/" target="_blank" title="Attribution-NonCommercial-NoDerivatives 4.0 International (CC BY-NC-ND 4.0)">署名-非商业性使用-禁止演绎 4.0 国际</a> 转载请保留原文链接及作者。</p>  
  </div>
  


          <div class="post-tags">
              <a href="/tags/LV16-STM32%E5%BC%80%E5%8F%91/" rel="tag"><i class="fa fa-tag"></i> LV16-STM32开发</a>
          </div>

        

          <div class="post-nav">
            <div class="post-nav-item">
                <a href="/post/90b770f9.html" rel="prev" title="LV16-27-内部Flash-02-Flash操作过程">
                  <i class="fa fa-angle-left"></i> LV16-27-内部Flash-02-Flash操作过程
                </a>
            </div>
            <div class="post-nav-item">
                <a href="/post/a48d1139.html" rel="next" title="LV16-26-LCD-07-任意大小字模？">
                  LV16-26-LCD-07-任意大小字模？ <i class="fa fa-angle-right"></i>
                </a>
            </div>
          </div>
    </footer>
  </article>
</div>






</div>
  </main>

  <footer class="footer">
    <div class="footer-inner">

  <div class="copyright">
    &copy; 2017 – 
    <span itemprop="copyrightYear">2025</span>
    <span class="with-love">
      <i class="fa fa-heart"></i>
    </span>
    <span class="author" itemprop="copyrightHolder">苏木</span>
  </div>
<div class="wordcount">
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-chart-line"></i>
    </span>
      <span>站点总字数：</span>
    <span title="站点总字数">3.7m</span>
  </span>
  <span class="post-meta-item">
    <span class="post-meta-item-icon">
      <i class="fa fa-coffee"></i>
    </span>
      <span>站点阅读时长 &asymp;</span>
    <span title="站点阅读时长">225:26</span>
  </span>
</div>




    <span id="sitetime"></span>
    <script defer language=javascript>
        function siteTime()
        {
            window.setTimeout("siteTime()", 1000);
            var seconds = 1000;
            var minutes = seconds * 60;
            var hours = minutes * 60;
            var days = hours * 24;
            var years = days * 365;
            var today = new Date();
            var todayYear = today.getFullYear();
            var todayMonth = today.getMonth()+1;
            var todayDate = today.getDate();
            var todayHour = today.getHours();
            var todayMinute = today.getMinutes();
            var todaySecond = today.getSeconds();
            /*==================================================
            Date.UTC() -- 返回date对象距世界标准时间(UTC)1970年1月1日午夜之间的毫秒数(时间戳)
            year        - 作为date对象的年份，为4位年份值
            month       - 0-11之间的整数，做为date对象的月份
            day         - 1-31之间的整数，做为date对象的天数
            hours       - 0(午夜24点)-23之间的整数，做为date对象的小时数
            minutes     - 0-59之间的整数，做为date对象的分钟数
            seconds     - 0-59之间的整数，做为date对象的秒数
            microseconds - 0-999之间的整数，做为date对象的毫秒数
            ==================================================*/
            var t1 = Date.UTC(2017, 
                              5, 
                              19, 
                              0, 
                              0, 
                              0); //北京时间
            var t2 = Date.UTC(todayYear,todayMonth,todayDate,todayHour,todayMinute,todaySecond);
            var diff = t2-t1;
            var diffYears = Math.floor(diff/years);
            var diffDays = Math.floor((diff/days)-diffYears*365);
            var diffHours = Math.floor((diff-(diffYears*365+diffDays)*days)/hours);
            var diffMinutes = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours)/minutes);
            var diffSeconds = Math.floor((diff-(diffYears*365+diffDays)*days-diffHours*hours-diffMinutes*minutes)/seconds);
            document.getElementById("sitetime").innerHTML="已在这里 "+diffYears+" 年 "+diffDays+" 天 "+diffHours+" 小时 "+diffMinutes+" 分钟 "+diffSeconds+" 秒";
        }
        siteTime();
    </script>



    </div>
  </footer>

  
  <div class="back-to-top" role="button" aria-label="返回顶部">
    <i class="fa fa-arrow-up fa-lg"></i>
    <span>0%</span>
  </div>
  <div class="reading-progress-bar"></div>

<noscript>
  <div class="noscript-warning">Theme NexT works best with JavaScript enabled</div>
</noscript>


  
  <script src="https://cdnjs.cloudflare.com/ajax/libs/animejs/3.2.1/anime.min.js" integrity="sha256-XL2inqUJaslATFnHdJOi9GfQ60on8Wx1C2H8DYiN1xY=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/next-theme-pjax/0.6.0/pjax.min.js" integrity="sha256-vxLn1tSKWD4dqbMRyv940UYw4sXgMtYcK6reefzZrao=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/fancyapps-ui/5.0.28/fancybox/fancybox.umd.js" integrity="sha256-ytMJGN3toR+a84u7g7NuHm91VIR06Q41kMWDr2pq7Zo=" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/lozad.js/1.16.0/lozad.min.js" integrity="sha256-mOFREFhqmHeQbXpK2lp4nA3qooVgACfh88fpJftLBbc=" crossorigin="anonymous"></script>
<script src="/js/comments.js"></script><script src="/js/utils.js"></script><script src="/js/motion.js"></script><script src="/js/next-boot.js"></script><script src="/js/pjax.js"></script>

  <script src="https://cdnjs.cloudflare.com/ajax/libs/hexo-generator-searchdb/1.4.1/search.js" integrity="sha256-1kfA5uHPf65M5cphT2dvymhkuyHPQp5A53EGZOnOLmc=" crossorigin="anonymous"></script>
<script src="/js/third-party/search/local-search.js"></script>




  <script src="/js/third-party/fancybox.js"></script>

  <script src="/js/third-party/pace.js"></script>


  




  

  <script class="next-config" data-name="enableMath" type="application/json">true</script><script class="next-config" data-name="mathjax" type="application/json">{"enable":true,"tags":"none","js":{"url":"https://cdnjs.cloudflare.com/ajax/libs/mathjax/3.2.2/es5/tex-mml-chtml.js","integrity":"sha256-MASABpB4tYktI2Oitl4t+78w/lyA+D7b/s9GEP0JOGI="}}</script>
<script src="/js/third-party/math/mathjax.js"></script>


 
        <div id="click-show-text"
            data-mobile = false
            data-text = 富强,民主,文明,和谐,自由,平等,公正,法制,爱国,敬业,诚信,友善
            data-fontsize = 15px
            data-random= false>
        </div>
       

      
        <script async src=https://cdn.jsdelivr.net/npm/hexo-next-mouse-effect@latest/click/showText.js></script>
      

      
    




    <script async src="/js/fancybox_param.js"></script>





<!-- APlayer本体 -->



</body>
</html>
